package com.elock.service.serviceImpl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.elock.base.core.Filter;
import com.elock.base.core.Page;
import com.elock.base.core.Pageable;
import com.elock.base.core.service.impl.BaseServiceImpl;
import com.elock.base.core.util.ConvertUtil;
import com.elock.base.core.util.ExceptionUtil;
import com.elock.dao.TerminalDao;
import com.elock.entity.Car;
import com.elock.entity.SaleOrg;
import com.elock.entity.SystemDict;
import com.elock.entity.Terminal;
import com.elock.entity.TerminalCar;
import com.elock.entity.TerminalOnline;
import com.elock.entity.TerminalRealtimePosition;
import com.elock.entity.TerminalSaleOrg;
import com.elock.service.CarService;
import com.elock.service.MemberService;
import com.elock.service.SaleOrgBaseService;
import com.elock.service.SystemDictBaseService;
import com.elock.service.TerminalCarService;
import com.elock.service.TerminalOnlineService;
import com.elock.service.TerminalRealtimePositionService;
import com.elock.service.TerminalSaleOrgService;
import com.elock.service.TerminalService;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

/**
 * 终端设备
 * @author 仁德
 */
@Service("terminalServiceImpl")
public class TerminalServiceImpl extends BaseServiceImpl<Terminal>
		implements TerminalService {

	@Resource(name = "terminalSaleOrgServiceImpl")
	private TerminalSaleOrgService terminalSaleOrgService;
	@Resource(name = "terminalOnlineServiceImpl")
	private TerminalOnlineService terminalOnlineService;
	@Resource(name = "terminalRealtimePositionServiceImpl")
	private TerminalRealtimePositionService terminalRealtimePositionService;
	@Resource(name = "saleOrgBaseServiceImpl")
	private SaleOrgBaseService saleOrgBaseService;
	@Resource(name = "memberServiceImpl")
	private MemberService memberService;
	@Resource(name = "carServiceImpl")
	private CarService carService;
	@Resource(name = "terminalCarServiceImpl")
	private TerminalCarService terminalCarService;
	@Resource(name = "terminalDao")
	private TerminalDao terminalDao;
	@Resource(name = "systemDictBaseServiceImpl")
	private SystemDictBaseService systemDictBaseService;

	public void save(Terminal terminal, Long saleOrgId, Long[] carId) {

		this.save(terminal);

		Long terminalId = terminal.getId();
		String terminalNum = terminal.getTerminalNum();

		//设置终端设备机构关联
		if (saleOrgId != null) {
			TerminalSaleOrg terminalSaleOrg = new TerminalSaleOrg();
			terminalSaleOrg.setTerminalId(terminalId);
			terminalSaleOrg.setTerminalNum(terminalNum);
			terminalSaleOrg.setSaleOrgId(saleOrgId);
			terminalSaleOrgService.save(terminalSaleOrg);
		}

		//终端设备车辆关联
		if (carId != null && carId.length > 0) {
			for (Long id : carId) {
				TerminalCar tCar = new TerminalCar();
				tCar.setTerminalId(terminal.getId());
				tCar.setTerminalNum(terminal.getTerminalNum());
				tCar.setCarId(id);
				Car car = carService.find(id);
				tCar.setCarNumber(car.getCarNumber());
				terminalCarService.save(tCar);
			}
		}

		//终端是否在线
		TerminalOnline terminalOnline = new TerminalOnline();
		terminalOnline.setTerminalId(terminalId);
		terminalOnline.setTerminalNum(terminalNum);
		terminalOnlineService.save(terminalOnline);

		//终端实时位置信息
		TerminalRealtimePosition terminalRealtimePosition = new TerminalRealtimePosition();
		terminalRealtimePosition.setTerminalId(terminalId);
		terminalRealtimePosition.setTerminalNum(terminalNum);
		terminalRealtimePositionService.save(terminalRealtimePosition);
	}

	public void update(Terminal terminal, Long saleOrgId, Long[] carId) {

		this.update(terminal);

		//终端设备机构关联
		saveTerminalSaleOrg(saleOrgId, terminal);

//		//终端设备车辆关联
		saveTerminalCar(carId, terminal);
	}

	/**
	 * 保存终端设备机构关联
	 */
	public void saveTerminalSaleOrg(Long saleOrgId, Terminal terminal) {

		List<Filter> filters = new ArrayList<Filter>();
		filters.add(Filter.eq("terminalId", terminal.getId()));
		List<TerminalSaleOrg> terminalSaleOrgs = terminalSaleOrgService.findList(null,
				filters,
				null);
		TerminalSaleOrg terminalSaleOrg = null;
		for (TerminalSaleOrg org : terminalSaleOrgs) {
			if (saleOrgId != null && org.getSaleOrgId().equals(saleOrgId)) {
				terminalSaleOrg = org;
			}
			else {
				terminalSaleOrgService.delete(org);
			}
		}
		if (terminalSaleOrg == null && saleOrgId != null) {
			terminalSaleOrg = new TerminalSaleOrg();
			terminalSaleOrg.setTerminalId(terminal.getId());
			terminalSaleOrg.setTerminalNum(terminal.getTerminalNum());
			terminalSaleOrg.setSaleOrgId(saleOrgId);
			terminalSaleOrgService.save(terminalSaleOrg);
		}
	}

	/**
	 * 保存终端设备车辆关联
	 */
	public void saveTerminalCar(Long[] carId, Terminal terminal) {

		List<Filter> filters = new ArrayList<Filter>();
		filters.add(Filter.eq("terminalId", terminal.getId()));
		List<TerminalCar> terminalCars = terminalCarService.findList(null, filters, null);
		List<Long> oCarIds = new ArrayList<Long>();
		for (TerminalCar terminalCar : terminalCars) {
			oCarIds.add(terminalCar.getCarId());
		}

		List<Long> nCarIds = new ArrayList<Long>();
		if (carId != null && carId.length > 0) {
			for (Long nCarId : carId) {
				nCarIds.add(nCarId);
			}
		}

		for (Long nCarId : nCarIds) {
			if (!oCarIds.contains(nCarId)) {
				TerminalCar tCar = new TerminalCar();
				tCar.setTerminalId(terminal.getId());
				tCar.setTerminalNum(terminal.getTerminalNum());
				tCar.setCarId(nCarId);
				Car car = carService.find(nCarId);
				tCar.setCarNumber(car.getCarNumber());
				terminalCarService.save(tCar);
			}
		}

		for (TerminalCar tCar : terminalCars) {
			if (!nCarIds.contains(tCar.getCarId())) {
				terminalCarService.delete(tCar);
			}
		}
	}

	public Page<Map<String, Object>> findPage(String terminalNum, String terminalName,
			Long saleOrgId, String sim, Pageable pageable) {
		return terminalDao.findPage(terminalNum, terminalName, saleOrgId, sim, pageable);
	}

	public List<Map<String, Object>> findTerminalElectronicFenceByTerminalId(
			Long terminalId) {
		return terminalDao.findTerminalElectronicFenceByTerminalId(terminalId);
	}

	public Terminal findByCarNumber(String terminalNum) {
		return terminalDao.findByCarNumber(terminalNum);
	}

	public Page<Map<String, Object>> findTerminalMonitorPage(String terminalNum,
			String sim, Long saleOrgId, String startTime, String endTime,
			Pageable pageable) {
		return terminalDao.findTerminalMonitorPage(terminalNum,
				sim,
				saleOrgId,
				startTime,
				endTime,
				pageable);
	}

	public Integer countTerminalMonitor(String terminalNum, String sim, Long saleOrgId,
			String startTime, String endTime, Pageable pageable, Integer page,
			Integer size) {
		return terminalDao.countTerminalMonitor(terminalNum,
				sim,
				saleOrgId,
				startTime,
				endTime,
				pageable,
				page,
				size);
	}

	public List<Map<String, Object>> findTerminalMonitorList(String terminalNum,
			String sim, Long saleOrgId, String startTime, String endTime,
			Pageable pageable, Integer page, Integer size) {
		return terminalDao.findTerminalMonitorList(terminalNum,
				sim,
				saleOrgId,
				startTime,
				endTime,
				pageable,
				page,
				size);
	}

	public Integer countTerminalList(String terminalNum, String terminalName,
			Long saleOrgId, String sim, Pageable pageable, Integer page, Integer size) {
		return terminalDao.countTerminalList(terminalNum,
				terminalName,
				saleOrgId,
				sim,
				pageable,
				page,
				size);
	}

	public List<Map<String, Object>> findTerminalList(String terminalNum,
			String terminalName, Long saleOrgId, String sim, Pageable pageable,
			Integer page, Integer size) {
		return terminalDao.findTerminalList(terminalNum,
				terminalName,
				saleOrgId,
				sim,
				pageable,
				page,
				size);
	}

	public String terminalImport(MultipartFile multipartFile) throws Exception {

		String msg = "";
		Workbook wb = null;
		File tempFile = null;
		Cell cell = null;
		int success = 0;
		try {
			tempFile = new File(System.getProperty("java.io.tmpdir")
					+ "/upload_"
					+ UUID.randomUUID()
					+ ".tmp");
			if (!tempFile.getParentFile().exists()) {
				tempFile.getParentFile().mkdirs();
			}
			multipartFile.transferTo(tempFile);
			wb = Workbook.getWorkbook(tempFile);
			Sheet sheet = wb.getSheets()[0];
			int rows = sheet.getRows();
			if (rows > 1001) {
				if (StringUtils.isNotBlank(sheet.getCell(0, 5000).getContents())) {
					ExceptionUtil.throwServiceException("一次最多导入1000条");
				}
				else {
					rows = 1001;
				}
			}

			String terminalNum; // 终端设备编号
			String terminalName; // 终端设备名称
			String sim; // 终端SIM卡号
			String typeName; // 终端设备类型
			String modelName; // 终端设备型号
			String isJzdw; // 是否开启基站定位
			String isManualUnlock; // 是否手动开锁
			String isManualRemoveWarn; // 是否手动解除报警
			String saleOrgSn; // 机构编号
			String remark; // 备注

			List<Filter> filters = new ArrayList<Filter>();
			for (int i = 1; i < rows; i++) {

				cell = sheet.getCell(0, i);
				terminalNum = cell.getContents().trim();
				if (ConvertUtil.isEmpty(terminalNum)) {
					ExceptionUtil
							.throwServiceException("第" + (i + 1) + "行." + "终端设备编号未填写");
				}
				if (terminalNum.length() != 8) {
					ExceptionUtil.throwServiceException(
							"第" + (i + 1) + "行." + "终端设备编号必须是8个字符");
				}
				Terminal t = findByCarNumber(terminalNum);
				if (t != null) {
					ExceptionUtil.throwServiceException(
							"第" + (i + 1) + "行." + "该终端设备编号在系统中已存在");
				}

				cell = sheet.getCell(1, i);
				terminalName = cell.getContents().trim();
				if (ConvertUtil.isEmpty(terminalName)) {
					ExceptionUtil
							.throwServiceException("第" + (i + 1) + "行." + "终端设备名称未填写");
				}

				cell = sheet.getCell(2, i);
				sim = cell.getContents().trim();
				if (ConvertUtil.isEmpty(sim)) {
					ExceptionUtil
							.throwServiceException("第" + (i + 1) + "行." + "终端SIM卡号未填写");
				}

				cell = sheet.getCell(3, i);
				typeName = cell.getContents().trim();
				SystemDict type = null;
				if (!ConvertUtil.isEmpty(typeName)) {
					filters.clear();
					filters.add(Filter.eq("code", "TerminalType"));
					filters.add(Filter.eq("value", typeName));
					filters.add(Filter.isNotNull("parent"));
					type = systemDictBaseService.find(filters);
					if (type == null) {
						ExceptionUtil.throwServiceException("第"
								+ (i + 1)
								+ "行."
								+ "终端设备类型["
								+ typeName
								+ "]在系统中不存在");
					}
				}

				cell = sheet.getCell(4, i);
				modelName = cell.getContents().trim();
				SystemDict model = null;
				if (!ConvertUtil.isEmpty(modelName)) {
					filters.clear();
					filters.add(Filter.eq("code", "TerminalModel"));
					filters.add(Filter.eq("value", modelName));
					filters.add(Filter.isNotNull("parent"));
					model = systemDictBaseService.find(filters);
					if (model == null) {
						ExceptionUtil.throwServiceException("第"
								+ (i + 1)
								+ "行."
								+ "终端设备型号["
								+ typeName
								+ "]在系统中不存在");
					}
				}

				cell = sheet.getCell(5, i);
				isJzdw = cell.getContents().trim();
				if (ConvertUtil.isEmpty(isJzdw)) {
					ExceptionUtil
							.throwServiceException("第" + (i + 1) + "行." + "是否开启基站定位未填写");
				}
				if (!isJzdw.equals("是") && !isJzdw.equals("否")) {
					ExceptionUtil.throwServiceException(
							"第" + (i + 1) + "行." + "是否开启基站定位请填写'是'或'否'");
				}

				cell = sheet.getCell(6, i);
				isManualUnlock = cell.getContents().trim();
				if (ConvertUtil.isEmpty(isManualUnlock)) {
					ExceptionUtil
							.throwServiceException("第" + (i + 1) + "行." + "是否手动开锁未填写");
				}
				if (!isManualUnlock.equals("是") && !isManualUnlock.equals("否")) {
					ExceptionUtil.throwServiceException(
							"第" + (i + 1) + "行." + "是否手动开锁请填写'是'或'否'");
				}

				cell = sheet.getCell(7, i);
				isManualRemoveWarn = cell.getContents().trim();
				if (ConvertUtil.isEmpty(isManualRemoveWarn)) {
					ExceptionUtil
							.throwServiceException("第" + (i + 1) + "行." + "是否手动解除报警未填写");
				}
				if (!isManualRemoveWarn.equals("是") && !isManualRemoveWarn.equals("否")) {
					ExceptionUtil.throwServiceException(
							"第" + (i + 1) + "行." + "是否手动解除报警请填写'是'或'否'");
				}

				cell = sheet.getCell(8, i);
				saleOrgSn = cell.getContents().trim();
				SaleOrg saleOrg = null;
				if (!ConvertUtil.isEmpty(saleOrgSn)) {
					filters.clear();
					filters.add(Filter.eq("sn", saleOrgSn));
					saleOrg = saleOrgBaseService.find(filters);
					if (saleOrg == null) {
						ExceptionUtil.throwServiceException("第"
								+ (i + 1)
								+ "行."
								+ "机构编号为["
								+ saleOrgSn
								+ "]的机构在系统中不存在");
					}
				}

				cell = sheet.getCell(9, i);
				remark = cell.getContents().trim();

				saveTerminal(terminalNum,
						terminalName,
						sim,
						type,
						model,
						isJzdw,
						isManualUnlock,
						isManualRemoveWarn,
						saleOrg,
						remark);

				success++;
			}

			int result = rows - 1;
			msg = "msg:" + "总数" + result + "行,成功导入" + success + " 行. ";
		}
		finally {

		}

		return msg;
	}

	public void saveTerminal(String terminalNum, String terminalName, String sim,
			SystemDict type, SystemDict model, String isJzdw, String isManualUnlock,
			String isManualRemoveWarn, SaleOrg saleOrg, String remark) {

		Terminal terminal = new Terminal();
		terminal.setTerminalNum(terminalNum);
		terminal.setTerminalName(terminalName);
		terminal.setSim(sim);
		terminal.setType(type);
		terminal.setModel(model);
		terminal.setIsJzdw(isJzdw.equals("是") ? true : false);
		terminal.setIsManualUnlock(isManualUnlock.equals("是") ? true : false);
		terminal.setIsManualRemoveWarn(isManualRemoveWarn.equals("是") ? true : false);
		terminal.setRemark(remark);
		this.save(terminal);

		//终端是否在线
		TerminalOnline terminalOnline = new TerminalOnline();
		terminalOnline.setTerminalId(terminal.getId());
		terminalOnline.setTerminalNum(terminalNum);
		terminalOnlineService.save(terminalOnline);

		//终端实时位置信息
		TerminalRealtimePosition terminalRealtimePosition = new TerminalRealtimePosition();
		terminalRealtimePosition.setTerminalId(terminal.getId());
		terminalRealtimePosition.setTerminalNum(terminalNum);
		terminalRealtimePositionService.save(terminalRealtimePosition);

		if (saleOrg != null) {
			TerminalSaleOrg terminalSaleOrg = new TerminalSaleOrg();
			terminalSaleOrg.setTerminalId(terminal.getId());
			terminalSaleOrg.setTerminalNum(terminal.getTerminalNum());
			terminalSaleOrg.setSaleOrgId(saleOrg.getId());
			terminalSaleOrgService.save(terminalSaleOrg);
		}

	}
}
